#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#include "general.h"
#include "stack.h"

Stack newStack(void)
{
  Stack new;
  new = calloc(1, sizeof(Stack_T));
  if (new == NULL)
    {
      fprintf(stderr, "newStack() unable to allocate memory!\n");
    }
  new->top = 0;
  new->num = 0;
  return new;
}

void delStack(Stack s)
{
  free(s);
}

int isStackEmpty(Stack s)
{
  if (s->top == 0) return 1;
  else return 0;
}

void push(Stack s, StackElement e)
{
  int top;
  s->num++;

  while (1)			/* blocking until pushed */
    {
      top = s->top;
      if (incStackPtr(top) >= STACK_DEPTH) continue; /* no more space */
      if (top < 0) continue;
      if (__sync_bool_compare_and_swap(&(s->top), top, -1))
      	{
	  s->stack[top].element = e->element;
	  while(!__sync_bool_compare_and_swap(&(s->top), -1, incStackPtr(top)));
	  return;		/* push successful */
      	}
    }
}

void pop(Stack s, StackElement e)
{
  int top;
  s->num--;

  while (1)
    {
      top = s->top;
      if (top <= 0) continue; /* nothing to pop */
      if (__sync_bool_compare_and_swap(&(s->top), top, -1))
      	{
	  top = decStackPtr(top); 
      	  e->element = s->stack[top].element;
      	  s->stack[top].element = NULL;
	  while(!__sync_bool_compare_and_swap(&(s->top), -1, top));
      	  return;
      	}
    }
}
